﻿package monitoring.resource;

/**
 * ADAMS Engine Core. 
 * Copyright ⓒ 2010 LGHitachi Co., Ltd. All Rights Reserved.
 * 
 * @Program Name : AIXResource.java
 * @Description : AIX장비 자원 반환 로직이 존재한다.
 * 
 * @author ADAMS Team
 * @version 1.0
 * @history 2010. 10. 14. - 작성
 */

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.DecimalFormat;

import util.Util;

public class AIXResource implements Resource{

    private static AIXResource aixResource = new AIXResource();
    
    private AIXResource(){};
    
    //Singleton
    public static AIXResource getInstance() {
        if(aixResource == null) aixResource = new AIXResource();
        return aixResource;
    }
    
    /**
     * AIX장비에서 shell 명령어를 수행하고 결과를 반환한다.
     * @param command AIX 외부명령  
     * @return AIX명령을 하고 나온 결과를 StringBuffer로 출력.
     */
    private StringBuffer executeCommand(String inputCommand) throws Exception{
        
        StringBuffer buffer = new StringBuffer();
        Process p = null;
        String ouputString = null;
        String errorString = null;
        
        String[] command = {"sh","-c", inputCommand};
        p = new ProcessBuilder(command).start();

        //process hasn't exited 에러방지
        p.waitFor();
        
        // 외부 프로그램 출력 읽기
        BufferedReader stdOut = new BufferedReader(new InputStreamReader(
                p.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(
                p.getErrorStream()));

        // "표준 출력"과 "표준 에러 출력"을 출력
        while ((ouputString = stdOut.readLine()) != null){
//                System.out.println(ouputString);
            buffer.append(ouputString);
        } 
        while ((errorString = stdError.readLine()) != null){
            System.out.println(errorString);
        }
            
        //에러 check
//        if(p.exitValue() != 0){
//            Exception e = new Exception("[ " + inputCommand + " ] 명령이 비정상적으로 종료 되었습니다.");
//            throw e;
//        }
//        
        return buffer ;
    }
    
    /*
     * 01.CPU 장비
     */
    
    /**
     * 물리적인 CPU갯수
     * @return 장비의 물리적인 CPU갯수
     */
    public int getCPUCount() {
        
        int cpuCount = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "lsdev -Cc processor | wc -l";
            buffer = executeCommand(command);
            cpuCount = Util.stoi(buffer.toString().trim());
//            System.out.println("cpuCount : " + cpuCount);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return cpuCount;
    }

    /**
     * CPU 속도
     * @return  CPU장비의 속도 MHz단위로 나온다. String 
     */
    public int getCPUSpeed() {
        int cpuSpeed = 0;
        
        StringBuffer buffer = new StringBuffer();
        
        try{
            String command = "pmcycles | awk '{print $5 $6}' ";
            buffer = executeCommand(command);
            cpuSpeed = Util.stoi(buffer.toString().trim().replace("MHz", ""));
//            System.out.println("cpuSpeed : " + cpuSpeed);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return cpuSpeed;
    }

    /**
     * CPU 사용률
     * @return 
     */
    public int getCPUUseage() {
        int cpuUseage = 0;
        int cpuIdle = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "vmstat | tail -1  | awk '{print $16}'";
            buffer = executeCommand(command);
            cpuIdle = Util.stoi(buffer.toString().trim()); //idle(%)
            cpuUseage = 100 - cpuIdle;
//            System.out.println("cpuIdle : " + cpuIdle);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return cpuUseage;
    }

    /**
     * 논리적인 CPU코어수 (듀얼코어는 물리CPU의 2배이다.)
     * @return 논리 CPU코어수 int이다.
     */
    public int getCoreCount() {
        int cpuCoreCount = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "pmcycles  -m | wc -l";
            buffer = executeCommand(command);
            cpuCoreCount = Util.stoi(buffer.toString().trim());
//            System.out.println("cpuCoreCount : " + cpuCoreCount);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return cpuCoreCount;
    }
    
    /*
     * 02.Memory 장비
     */
    
    /**
     * 메모리 사용률
     * @return 물리메모리 사용률 int(%)
     */
    public int getMemoryUseage() {
        String pattern = "#####";
        DecimalFormat dformat = new DecimalFormat( pattern );
        
        int PhysicalMemory = getPhysicalMemory();
        float MemoryUse = getMemoryUse();
        
        float MemoryUseage = (MemoryUse / (float)PhysicalMemory)*100 ;
        
        return Util.stoi(dformat.format(MemoryUseage));
    }
    
    /**
     * 메모리 사용량
     * @return 물리메모리 사용량 float(MB)
     */
    public float getMemoryUse(){
        
        String pattern = "#####.##";
        DecimalFormat dformat = new DecimalFormat( pattern );
        
        long free  = Runtime.getRuntime().freeMemory();
        long total = Runtime.getRuntime().totalMemory();
//        long max   = Runtime.getRuntime().maxMemory();
        
        float MemoryUse = 0f;
        
        MemoryUse = (float)(total - free)/(1024 * 1024);
        
        return Util.stof(dformat.format(MemoryUse));
    }
    
    /**
     * 물리메모리 용량
     * @return 물리적인 메모리총용량 int(MB)
     */
    public int getPhysicalMemory() {
        int PhysicalMemory = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "lsattr -E -l mem0 -a size | awk '{print $2}' ";
            buffer = executeCommand(command);
            PhysicalMemory = Util.stoi(buffer.toString().trim());
//            System.out.println("PhysicalMemory : " + PhysicalMemory);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return PhysicalMemory;
    }
    
    /**
     * Swap메모리 용량
     * @return Disk메모리용량 int(MB)
     */
    public int getSwapMemory() {
        int SwapMemory = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "lsps -a | tail -1 | awk {'print $4'} ";
            buffer = executeCommand(command);
            SwapMemory = Util.stoi(buffer.toString().trim().replace("MB", ""));
//            System.out.println("SwapMemory : " + SwapMemory);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return SwapMemory;
    }
    
    
    /*
     * 03.Disk 장비 
     */
    
    /**
     *  물리적인 Disk갯수
     *  @return 물리적인 HDD Disk갯수 int(갯수)
     */
    public int getDiskCount() {
        int DiskCount = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "lspv |wc -l ";
            buffer = executeCommand(command);
            DiskCount = Util.stoi(buffer.toString().trim());
//            System.out.println("DiskCount : " + DiskCount);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return DiskCount;
    }

    /**
     * Disk 총용량
     * @return Mirror Disk일경우에는 총용량의 반이라고 생각하면됨 int(MB)
     */
    public int getDiskTotalCapacity() {
        int DiskTotalCapacity = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            String command = "lspv hdisk0 | grep 'TOTAL PPs' | awk -F'(' '{print $2}' | awk '{print $1}' ";
            buffer = executeCommand(command);
            DiskTotalCapacity = Util.stoi(buffer.toString().trim());
//            System.out.println("DiskTotalCapacity : " + DiskTotalCapacity);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return DiskTotalCapacity;
    }
    
    /**
     * Disk 사용률(%)
     * @return 현재 디렉토리의 디스크사용량 int(%)
     */
    public int getDiskuseage() {
        int Diskuseage = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            //현재디렉토리 사용량
            String command = "df -m . | tail -1 | awk {'print $4'} ";
            buffer = executeCommand(command);
            Diskuseage = Util.stoi(buffer.toString().trim().replace("%", ""));
//            System.out.println("Diskuseage : " + Diskuseage);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return Diskuseage;
    }

    /**
     * Disk IQ 발생률
     * @return Disk의 IO발생률 int(%)
     */
    public float getIO_idle() {
        float IO_idle = 0;
        StringBuffer buffer = new StringBuffer();
        
        try {
            //현재디렉토리 사용량
            String command = "iostat -a  | head -5 | tail -1 | awk {'print $5'} ";
            buffer = executeCommand(command);
            IO_idle = Util.stof(buffer.toString().trim());
//            System.out.println("Diskuseage : " + Diskuseage);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return IO_idle;
    }

    /*
     * 04.정보성
     */

    public int getNetworkTraffic() {
        // TODO Auto-generated method stub
        return 0;
    }

    /**
     * 서버장비의 OS명을 가져온다.
     * @return 서버장비의 OS버전명 String
     */
    public String getOS_Name() {
        String OS_Name = "";
        StringBuffer buffer = new StringBuffer();
        
        try {
            //현재디렉토리 사용량
            String command = "echo `uname -s` `uname -v`.`uname -r` ";
            buffer = executeCommand(command);
            OS_Name = buffer.toString().trim();
//            System.out.println("OS_Name : " + OS_Name);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return OS_Name;
    }

    /**
     * 서버장비 모델명을 가져온다.
     * @return 서버장비 모델명 (String)
     */
    public String getServerName() {
        String ServerName = "";
        StringBuffer buffer = new StringBuffer();
        
        try {
            //현재디렉토리 사용량
            String command = "lsattr -E -l sys0 | awk '/modelname/ {print $2}' ";
            buffer = executeCommand(command);
            ServerName = buffer.toString().trim();
//            System.out.println("ServerName : " + ServerName);
        } catch (Exception e) {
            System.out.println("에러! 외부 명령 실행에 실패했습니다.\n" + e.getMessage());
        }
        
        return ServerName;
    }

}
